/*
 * Copyright 2012 Marsrutai.lt
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package lt.marsrutai.mobile.android.util;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.ProtocolException;
import java.util.zip.GZIPInputStream;

import org.apache.http.Header;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.impl.client.DefaultHttpClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import android.net.Uri;

public class HttpGetRequest {

    private static final Logger logger = LoggerFactory.getLogger("HttpGetRequest");

	private String uri;
	private Integer contentLength;
	private CalculatingInputStream cis;

	public HttpGetRequest(String uri) {
		this.uri = Uri.encode(uri, "/?&:=");
	}
	
	public InputStream getStream() throws IOException {
	    DefaultHttpClient httpClient = new DefaultHttpClient();
        HttpUriRequest request = new HttpGet(uri);
        request.setHeader("Accept-Encoding", "gzip");

        long startTime = System.currentTimeMillis();
        logger.debug(uri);
        HttpResponse response = httpClient.execute(request);
        logger.debug("Received response in [{}ms].", System.currentTimeMillis() - startTime);

        if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
            throw new ProtocolException("Status code " + response.getStatusLine().getStatusCode() + " for request " + uri);
        }

        cis = new CalculatingInputStream(response.getEntity().getContent());
        InputStream inputStream = cis;
        Header contentEncoding = response.getFirstHeader("Content-Encoding");
        if (contentEncoding != null && contentEncoding.getValue().equalsIgnoreCase("gzip")) {
            inputStream = new GZIPInputStream(inputStream);
        }
        
        Header contentLengthHeader = response.getFirstHeader("Content-Length");
        if (contentLengthHeader != null) {
            try {
                contentLength = Integer.valueOf(contentLengthHeader.getValue());
            }
            catch (NumberFormatException ex) {
                contentLength = 0;
                logger.info(String.format("Unable to parse Content-Length from %s."), contentLengthHeader.getValue());
            }
        }

        return inputStream;
	}
	
	public String download() throws IOException {
	    return convertStreamToString(getStream(), 512);
	}
	
	public Integer getContentLength() {
	    return contentLength;
	}
	
	public Integer getReadCount() {
	    return cis.getReadCount();
	}
	
	private String convertStreamToString(final InputStream is, final int bufferSize) throws IOException {
        final char[] buffer = new char[bufferSize];
        final StringBuilder out = new StringBuilder();

        final Reader in = new InputStreamReader(is);
        try {
            for (;;) {
                int rsz = in.read(buffer, 0, buffer.length);
                if (rsz < 0)
                    break;
                out.append(buffer, 0, rsz);
            }
        }
        finally {
            in.close();
        }

        return out.toString();
    }

}
